package com.changgou.seckill.mq;

import com.alibaba.fastjson.JSON;
import com.changgou.seckill.dao.SeckillGoodsMapper;
import com.changgou.seckill.pojo.SeckillGoods;
import com.changgou.seckill.pojo.SeckillOrder;
import com.changgou.seckill.pojo.SeckillStatus;
import com.changgou.util.IdWorker;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * @Author tang.qingbo
 * @Date 2020/9/9 14:46
 * @Version 1.0
 */
@Component
@RabbitListener(queues = "seckillOrderQueue")
public class SeckillOrderConsumer {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;


    /**
     * 秒杀下单,监听队列的抢单信息,读取到进行下单处理
     * @param message 队列中的抢单信息
     */
    @RabbitHandler
    public void readOrderMessage(String message) {
        //将队列中的抢单信息转为SeckillStatus
        SeckillStatus seckillStatus = JSON.parseObject(message, SeckillStatus.class);
        //获取当前用户
        String username = seckillStatus.getUsername();

        //获取下单信息==>判断当前用户是否已经下单
        //Object seckillOrder = redisTemplate.boundHashOps("SeckillOrder").get(username);
        //if (seckillOrder != null) {
        //    System.out.println("存在未支付订单,不允许排队下单");
        //    return;
        //}

        //从redis队列中获取数据,判断该商品是否还有库存== 直接从队列的右侧弹出一个需要下单的商品数据
        Object goodsId = redisTemplate.boundListOps("SeckillGoodsCountList_" + seckillStatus.getGoodsId()).rightPop();
        if (goodsId == null) {
            /**
             * 说明没有库存了
             *      1. 清除之前的抢单信息
             *      2. 清除排队信息
             *      3. 结束方法执行
             */
            //清除抢单信息
            stringRedisTemplate.delete("SeckillStatus_" + username);
            //清除排队信息
            redisTemplate.delete("UserQueueCount_" + username);

            return;
        }

        //查询redis中存有的当前商品信息
        SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps("SeckillGoods_" + seckillStatus.getTime()).get(seckillStatus.getGoodsId());

        //判断获取到的商品是否为空 && 库存数量是否 > 0
        if (seckillGoods != null && seckillGoods.getStockCount() > 0) {
            //封装订单信息
            SeckillOrder skOrder = new SeckillOrder();
            skOrder.setId("No"+idWorker.nextId());
            skOrder.setSeckillId(seckillGoods.getId());
            skOrder.setMoney(seckillGoods.getCostPrice() + "");
            skOrder.setUserId(seckillStatus.getUsername());
            skOrder.setCreateTime(new Date());
            //未支付
            skOrder.setStatus("0");

            //将数据存入redis 用户名username 为 key
            redisTemplate.boundHashOps("SeckillOrder").put(seckillStatus.getUsername(), skOrder);

            //将redis中当前商品的库存 -1
            //seckillGoods.setStockCount(seckillGoods.getStockCount() - 1);

            //将商品的自增计数器进行递减
            Long count = redisTemplate.boundHashOps("SeckillGoodsCount").increment(seckillStatus.getGoodsId(), -1);
            //设置库存为==>递减后的商品库存
            seckillGoods.setStockCount(count.intValue());

            //判断是否售罄
            if (seckillGoods.getStockCount() == 0) {
                //说明售罄=== 1.将数据同步到数据库  2.redis中保存的数据删除
                //1. 同步到数据库
                seckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods);
                //2. 删除redis中保存的数据
                redisTemplate.boundHashOps("SeckillGoods_" + seckillStatus.getTime()).delete(seckillGoods.getId());
            } else {
                //替换redis中保存的数据
                redisTemplate.boundHashOps("SeckillGoods_" + seckillStatus.getTime()).put(seckillGoods.getId(), seckillGoods);
            }

            //更新redis中保存的抢单状态
            seckillStatus.setStatus(2);//等待支付
            seckillStatus.setOrderId(skOrder.getId());
            seckillStatus.setMoney(Float.parseFloat(skOrder.getMoney()));
            //修改status状态
            stringRedisTemplate.boundValueOps("SeckillStatus_"+seckillStatus.getUsername()).set(JSON.toJSONString(seckillStatus));
        }
    }
}
